﻿using System;
using System.Data;
using System.Web;
using System.Web.Security;
using System.Security.Cryptography;
using System.Text;
using System.IO;

namespace MyUtility
{
    /// <summary>
    /// Lớp chứa các hàm về mã hóa, giải mã
    /// </summary>
    public class MySecurity
    {
        private static byte[] IV = { 121, 122, 123, 124, 125, 126, 127, 128 };
        
        private static TripleDESCryptoServiceProvider des = new TripleDESCryptoServiceProvider();
  
        private static bool FixKey3DES(string key, out byte[] result)
        {
            result = null;
            if (key.Length > 32 || key.Length == 0) return false;
            key = key.PadRight(32, 'x');
            try
            {
                result = Convert.FromBase64String(key);
                return true;
            }
            catch
            {
                return false;
            }

        }

        /// <summary>
        /// Dùng để mã hóa mật khẩu hay dữ liệu đầu vào bằng các ký tự phức tạp dựa vào ký hiệu riêng là biến "key" .
        /// </summary>
        public static string TripleDES_En(string input, string key)
        {
            string encrypted = "";
            if (input == null) return null;
            if (input == "") return "";
            byte[] keys;
            if (FixKey3DES(key, out keys) == false)
                throw new Exception("Invalid key format");
            des.Key = keys;
            byte[] Code = UTF8Encoding.Unicode.GetBytes(input);
            encrypted = Convert.ToBase64String(des.CreateEncryptor(keys, IV).TransformFinalBlock(Code, 0, Code.Length));
            return encrypted;
        }

        /// <summary>
        /// Lớp này dùng để giải mã .
        /// </summary>
        public static string TripleDES_De(string input, string key)
        {
            string decrypted = "";
            if (input == null) return null;
            if (input == "") return "";
            byte[] keys;
            if (FixKey3DES(key, out keys) == false)
                throw new Exception("Invalid key format");
            des.Key = keys;
            try
            {
                byte[] Code = Convert.FromBase64String(input);
                decrypted = UTF8Encoding.Unicode.GetString(des.CreateDecryptor(keys, IV).TransformFinalBlock(Code, 0, Code.Length));
            }
            catch
            {
                return null;
            }
            return decrypted;
        }

        /// <summary>
        /// Mã hóa một cách đơn giản dữ liệu
        /// </summary>
        /// <param name="Data">Chuỗi cần mã hóa</param>
        /// <returns>Chuỗi đã được mã hóa</returns>
        public static string EnCodeData(string Data)
        {
            try
            {
                byte[] encbuff = System.Text.Encoding.Unicode.GetBytes(Data);
                return "L" + Convert.ToBase64String(encbuff);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi trong quá trình EnCode dữ liệu", ex);
            }
        }
        /// <summary>
        /// Giả mã chỗi đã được mã hóa bằng hàm EnCodeDate
        /// </summary>
        /// <param name="Data">Chuỗi cần giản mã</param>
        /// <returns>Chuỗi đã được giải mã</returns>
        public static string DeCodeData(string Data)
        {
            try
            {
                Data = Data.Substring(1, Data.Length - 1);
                byte[] decbuff = Convert.FromBase64String(Data);
                return System.Text.Encoding.Unicode.GetString(decbuff);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi trong quá trình DeCode dữ liệu", ex);
            }
        }

        public static string DeCodeBase64(string Data)
        {
            try
            {
                byte[] decbuff = Convert.FromBase64String(Data);
                return System.Text.Encoding.Unicode.GetString(decbuff);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi trong quá trình DeCode dữ liệu", ex);
            }
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        public static string EnCodeBase64_ASCII(string Data)
        {
            try
            {
                byte[] encbuff = System.Text.ASCIIEncoding.ASCII.GetBytes(Data);
                return Convert.ToBase64String(encbuff,Base64FormattingOptions.None);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi trong quá trình EnCode dữ liệu", ex);
            }
        }
        public static string DeCodeBase64_ASCII(string Data)
        {
            try
            {
                byte[] decbuff = Convert.FromBase64String(Data);
                return System.Text.ASCIIEncoding.ASCII.GetString(decbuff);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi trong quá trình EnCode dữ liệu", ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Data"></param>
        /// <returns></returns>
        public static string EnCodeBase64(string Data)
        {
            try
            {
                byte[] encbuff = System.Text.Encoding.Unicode.GetBytes(Data);
                return Convert.ToBase64String(encbuff);
            }
            catch (Exception ex)
            {
                throw new Exception("Lỗi trong quá trình EnCode dữ liệu", ex);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="strCode"></param>
        /// <returns></returns>
        public static string EnCodeBase64_GetMSISDN(string strCode)
        {
            try
            {
                byte[] encData_byte = new byte[strCode.Length];
                encData_byte = System.Text.Encoding.UTF8.GetBytes(strCode);
                string encodedData = Convert.ToBase64String(encData_byte);
                return encodedData;
            }
            catch (Exception e)
            {
                throw new Exception("Error in base64Encode" + e.Message);
            }

        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="strCode"></param>
        /// <returns></returns>
        public static string DeCodeBase64_GetMSISDN(string strCode)
        {
            try
            {
                System.Text.UTF8Encoding encoder = new System.Text.UTF8Encoding();
                System.Text.Decoder utf8Decode = encoder.GetDecoder();

                byte[] todecode_byte = Convert.FromBase64String(strCode);
                int charCount = utf8Decode.GetCharCount(todecode_byte, 0, todecode_byte.Length);
                char[] decoded_char = new char[charCount];
                utf8Decode.GetChars(todecode_byte, 0, todecode_byte.Length, decoded_char, 0);
                string result = new String(decoded_char);
                return result;
            }
            catch (Exception e)
            {
                throw new Exception("Error in base64Decode" + e.Message);
            }
        }
       
        /// <summary>
        /// Mã hóa dữ liệu theo thuật toán MD5
        /// </summary>
        /// <param name="Data">Chuỗi dữ liệu cần mã hóa</param>
        /// <returns>Trả về chuỗi dữ liệu đã được mã hóa</returns>
        public static string Encrypt_MD5(string Data)
        {
            try
            {
                return System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(Data, "MD5");
            }
            catch (Exception ex)
            {
                throw ex;
            }

        }

        /// <summary>
        /// Tao code bang ngay thang hien tai
        /// </summary>
        /// <returns></returns>
        public static string CreateCodeByDate()
        {
            return System.DateTime.Now.ToString("yyyyMMddHHmmssffffff");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="FormatDate"></param>
        /// <returns></returns>
        public static string CreateCodeByDate(string FormatDate)
        {
            try
            {
                return System.DateTime.Now.ToString(FormatDate);
            }
            catch
            {
                return System.DateTime.Now.ToString("yyyyMMddHHmmssffffff");
            }
        }

        /// <summary>
        /// Tạo random code với số gồm 5 chữ số
        /// </summary>
        /// <returns></returns>
        public static string GenerateRandomCode()
        {
            Random random = new Random();
            return random.Next(99999).ToString("0####");
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="Code"></param>
        /// <param name="CodePrefix"></param>
        /// <param name="LengthNumber"></param>
        /// <returns></returns>
        public static string CreateMaxCode(string Code, string CodePrefix,int LengthNumber)
        {
            string temp = Code.Replace(CodePrefix, "");

            int iCode = 0;
            if (int.TryParse(temp, out iCode))
            {
                return CodePrefix + CreateCode(LengthNumber, ++iCode);
            }
            else
            {
                return CodePrefix + CreateCode(LengthNumber, ++iCode);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="iLenght"></param>
        /// <param name="iNumber"></param>
        /// <returns></returns>
        public static string CreateCode(int iLenght, int iNumber)
        {

            Random random = new Random();
            switch (iLenght)
            {
                case 1:
                    return iNumber.ToString();
                case 2:
                    return iNumber.ToString("0#");
                case 3:
                    return iNumber.ToString("0##");
                case 4:
                    return iNumber.ToString("0###");
                case 5:
                    return iNumber.ToString("0####");
                case 6:
                    return iNumber.ToString("0#####");
                case 7:
                    return iNumber.ToString("0######");
                case 8:
                    return iNumber.ToString("0#######");
                case 9:
                    return iNumber.ToString("0########");
                default:
                    return iNumber.ToString("0####");
            }

        }

        #region Static Functions
        /// <summary>
        /// Encrypts a string
        /// </summary>
        /// <param name="PlainText">Text to be encrypted</param>
        /// <param name="Password">Password to encrypt with</param>
        /// <param name="Salt">Salt to encrypt with</param>
        /// <param name="HashAlgorithm">Can be either SHA1 or MD5</param>
        /// <param name="PasswordIterations">Number of iterations to do</param>
        /// <param name="InitialVector">Needs to be 16 ASCII characters long</param>
        /// <param name="KeySize">Can be 128, 192, or 256</param>
        /// <returns>An encrypted string</returns>
        public static string AESEncrypt(string PlainText, string Password, string Salt, string HashAlgorithm, int PasswordIterations, string InitialVector, int KeySize)
        {
            try
            {
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
                byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
                byte[] PlainTextBytes = Encoding.UTF8.GetBytes(PlainText);
                PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
                byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
                RijndaelManaged SymmetricKey = new RijndaelManaged();
                SymmetricKey.Mode = CipherMode.CBC;
                byte[] CipherTextBytes = null;
                using (ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes))
                {
                    using (MemoryStream MemStream = new MemoryStream())
                    {
                        using (CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write))
                        {
                            CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
                            CryptoStream.FlushFinalBlock();
                            CipherTextBytes = MemStream.ToArray();
                            MemStream.Close();
                            CryptoStream.Close();
                        }
                    }
                }
                return Convert.ToBase64String(CipherTextBytes);
            }
            catch (Exception a)
            {
                throw a;
            }
        }

        /// <summary>
        /// Decrypts a string
        /// </summary>
        /// <param name="CipherText">Text to be decrypted</param>
        /// <param name="Password">Password to decrypt with</param>
        /// <param name="Salt">Salt to decrypt with</param>
        /// <param name="HashAlgorithm">Can be either SHA1 or MD5</param>
        /// <param name="PasswordIterations">Number of iterations to do</param>
        /// <param name="InitialVector">Needs to be 16 ASCII characters long</param>
        /// <param name="KeySize">Can be 128, 192, or 256</param>
        /// <returns>A decrypted string</returns>
        public static string AESDecrypt(string CipherText, string Password, string Salt, string HashAlgorithm, int PasswordIterations, string InitialVector, int KeySize)
        {
            
            try
            {
                byte[] InitialVectorBytes = Encoding.ASCII.GetBytes(InitialVector);
                byte[] SaltValueBytes = Encoding.ASCII.GetBytes(Salt);
                byte[] CipherTextBytes = Convert.FromBase64String(CipherText);
                PasswordDeriveBytes DerivedPassword = new PasswordDeriveBytes(Password, SaltValueBytes, HashAlgorithm, PasswordIterations);
                byte[] KeyBytes = DerivedPassword.GetBytes(KeySize / 8);
                RijndaelManaged SymmetricKey = new RijndaelManaged();
                SymmetricKey.Mode = CipherMode.CBC;
                byte[] PlainTextBytes = new byte[CipherTextBytes.Length];
                int ByteCount = 0;
                using (ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes))
                {
                    using (MemoryStream MemStream = new MemoryStream(CipherTextBytes))
                    {
                        using (CryptoStream CryptoStream = new CryptoStream(MemStream, Decryptor, CryptoStreamMode.Read))
                        {

                            ByteCount = CryptoStream.Read(PlainTextBytes, 0, PlainTextBytes.Length);
                            MemStream.Close();
                            CryptoStream.Close();
                        }
                    }
                }
                return Encoding.UTF8.GetString(PlainTextBytes, 0, ByteCount);
            }
            catch (Exception a)
            {
                throw a;
            }
        }
        #endregion

        public static string AESEncrypt_Simple(string Content, string Password)
        {
            try
            {
                string key="FRsgyQERTdfgDFRS";
                return AESEncrypt(Content, Password, "IcOm", "SHA1", 2, key, 128);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        public static string AESDecrypt_Simple(string EncryptContent, string Password)
        {
            string key = "FRsgyQERTdfgDFRS";
            return AESDecrypt(EncryptContent, Password, "IcOm", "SHA1", 2, key, 128);
        }

        public static string EnCodeURL(string URL)
        {
            return HttpUtility.UrlEncode(URL);
        }

        public static string SHA1_Encrypt(string Content)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(Content, "SHA1");
        }

    }



   
}
